import {Hocuspocus} from '@hocuspocus/server';
import Document from "@hocuspocus/server/src/Document";
import * as Y from 'yjs';
// 创建Hocuspocus服务器实例
// 跟踪每个文档的客户端连接数
const documentMap: Map<string, Document> = new Map();
const server = new Hocuspocus({
    port: 1234,

    // 启用文档状态扩展，用于跟踪在线用户
    extensions: [],


    // 连接建立时的回调
    async onConnect(data: any) {
        console.log(`Client connected to document "${data.documentName}"`);

    },

    // 文档加载时的回调。
    // 当一个文档被第一个客户端访问时，会触发 onLoadDocument 方法
    // 如果这个文档之前被编辑过，保存到了documentMap中，重新加载到 Hocuspocus 中，并返回给客户端。
    async onLoadDocument(data: any) {

        console.log(`Client onLoadDocument to connectionSize: "${data.document.connections.size}"`);
        const documentContent: Document = documentMap.get(data.documentName);
        if (documentContent === undefined) {

            const ydoc = data.document;

            // 检查文档是否为空
            const ytext = ydoc.getText('quill');
            if (ytext.toString().length === 0) {
                // 设置初始内容（可选）
                ytext.insert(0, '欢迎使用协作编辑器');
            }

            console.log('onLoadDocument:', ytext.toString());
            console.log("------------------")
        } else {
            // 关键步骤：将缓存的 documentContent 内容应用到 data.document
            const targetDoc = data.document;
            const targetText = targetDoc.getText('quill');
            const sourceText = documentContent.getText('quill');

            // 关键修改：使用Yjs的applyDelta方法复制完整内容（包括格式）
            const sourceDelta = sourceText.toDelta();
            console.log('从缓存恢复的Delta内容:', JSON.stringify(sourceDelta, null, 2));
            targetText.applyDelta(sourceDelta);

            console.log('onLoadDocument: 从缓存恢复文档');

        }

        return data.document;
    },


    // 变更提交时的回调
    async onChange(data: any) {
        const {documentName, document, context, changes, update} = data;

        const quillText = document.getText('quill').toDelta();

        console.log('文档当前内容:', JSON.stringify(quillText, null, 0));
        printUpdate(update);
        console.log(`Changes submitted to document "${data.documentName}"`);
    },



    // 连接断开时的回调
    // 每一个连接断开时都会触发，当最后一个客户端断链时，Hocuspocus 会从内存中清空文档信息，因此需要自定义保存。
    async onDisconnect(data: any) {
        console.log(`Client disconnected from document "${data.documentName}",客户端连接数：${data.document.connections.size}`);
        // 减少文档的连接计数

        if (data.document.connections.size <= 0) {
            documentMap.set(data.documentName, data.document);
        }
    },
});

// 启动服务器
server.listen().then(() => {
    console.log('Hocuspocus server is running on port 1234');
});

function printUpdate(update: Uint8Array) {
    try { // 创建一个临时文档来解析变更
        const tempDoc = new Y.Doc();
        Y.applyUpdate(tempDoc, update);
        // 获取 Y.Text 对象（假设使用 'quill' 作为名称）
        const ytext = tempDoc.getText('quill');

        // 将 Y.Text 转换为 Quill Delta 格式
        const delta = ytext.toDelta();

        // 打印带格式的 Delta 对象
        console.log('文档内容（带格式）:', JSON.stringify(delta, null, 2));
    } catch (e) {
        console.error('打印更新内容时出错:', e);
    }
}